#!/usr/bin/env python
#
# monitor.py
#
# Version : 0.6
# Date : 20080423
#
# Author : Bernard Czenkusz
# Email  : bernie@skipole.co.uk

#
# monitor.py - starts the Skipole Monitor program
# Copyright (c) 2007 Bernard Czenkusz
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#

"""Main module that starts the Skipole Monitor

Skipole Monitor enables a user to specify hosts, which are regularly
pinged, and their status displayed via a built-in web server, as
green (all ok), yellow (some failures) or red (all failures).

Change of status of hosts, and groups of hosts can optionally
initiate emails and syslog messages

Hosts (and groups of hosts) are input and edited via a gui interface.
"""


import net
import validate
import thread
import os
import sys
import poller
import makehtml
import sm_syslog
import time
import maintain_lockfile

# NOGUI = 0 if a gui is to be run, or 1 if not

NOGUI = 0

ARGUMENT_ERROR = """Incorrect arguments.
Either no arguments, or the single argument "nogui" is allowed,
which runs the program without a gui interface.
"""

# Check arguments

if len(sys.argv) > 2:
    print ARGUMENT_ERROR
    sys.exit(1)

if len(sys.argv) == 2 :
    if sys.argv[1] == "nogui" :
        NOGUI = 1
    else:
        print ARGUMENT_ERROR
        sys.exit(2)


# If not NOGUI, then import the gui module
if not NOGUI:
    try:
        from sm_gui import gui
    except:
        print """ERROR: unable to start the graphical user interface.
This program requires the wxPython library, have you installed it?"""
        sys.exit(3)


def handle_error(error_string, exit_value):
    """Function takes an error string and exit code, and if NOGUI is set
       prints out the error to console, otherwise starts the gui which
       creates an error message.  The program then exits with the given
       exit code."""
    global NOGUI
    if NOGUI:
        print error_string
        print "Stopping and exiting the program"
    else:
        # set the error status and string in the validate module variables
        # so they can be read when the gui starts up
        validate.set_error(True, error_string)
        gui.maingui()
    net.PROGRAM_SHUTDOWN = True
    # Delete the lockfile
    maintain_lockfile.close()
    sys.exit(exit_value)


# load the configuration and network - from the net module
exit_value, error_string = net.start_network()
if exit_value != 0:
    # start_network() in the net module failed, so flag an error and exit
    handle_error(error_string, exit_value)


if not os.path.exists(net.net_cfg["NETWORK_DATA_FOLDER"]):
    try:
        os.mkdir(net.net_cfg["NETWORK_DATA_FOLDER"])
    except:
        handle_error("Unable to create the network data folder", 8)


# Check if a lock file exists in the data directory, and if not create one
exit_value, error_string = maintain_lockfile.start_lockfile()
if exit_value != 0:
    # start_lockfile() in the maintain_lockfile module failed, so flag an error and exit
    handle_error(error_string, exit_value)


# set up a thread to keep the access time of the lock file less than five seconds old
thread.start_new_thread(maintain_lockfile.lockfile_loop,())


# Start up the web server, must start this before polling, in case the
# socket is already bound - so this program terminates before it
# attempts to change any web pages.
if net.net_cfg["WEB_SERVER_ENABLED"]=="1":
    # Only start the web server if the config file says so
    import webserver
    # start the web server in a thread
    if not webserver.startup(net.net_cfg["PORT"]):
        # Web server failed to start, create error message
        if int(net.net_cfg["PORT"]) < 1023 and os.name == "posix":
            error_string="Failed to start web server; listenning on port " + str(net.net_cfg["PORT"]) + " may require superuser rights. Running this service as superuser is not advisable."
        else:
            error_string="Failed to start web server; port " + str(net.net_cfg["PORT"]) + " may be in use."
        # and exit the program with the error message
        handle_error(error_string, 11)


# clear and remake the http root folder
if not makehtml.new_httproot():
    handle_error("Could not write to the HTTP root folder", 12)

# Create header for html pages
makehtml.make_header()

# Create initial network loading page
makehtml.network_loading()

# Start the syslog logger, if it has been enabled.
sm_syslog.create_logger()

# create the initial html pages for each group and host
net.set_flag_html_refresh()
poller.refresh_html()

# Start polling and start the gui
if NOGUI:
    # argument nogui has been passed, so run the program without a gui
    poller.poller_loop()
else:
    # The program is to be run with a gui,
    # start the poller in a thread
    thread.start_new_thread(poller.poller_loop,())
    # And continue to the gui part of the program
    gui.maingui()

# To get to this point, either the poller loop has exited, or if a gui is running,
# the user has pressed the exit button.

# Flag other threads to shutdown
net.PROGRAM_SHUTDOWN = True

# Give other threads a chance to stop
time.sleep(4)

# Delete the lockfile
maintain_lockfile.close()

# And exit
sys.exit(0)

